package com.gengzp.system.controller;

import com.gengzp.common.annotations.OperationLogIgnore;
import com.gengzp.common.model.generic.resp.Result;
import com.gengzp.common.model.permission.req.AllocatePageReq;
import com.gengzp.common.model.permission.req.AllocatePermissionReq;
import com.gengzp.common.model.permission.req.AllocateRoleReq;
import com.gengzp.common.model.permission.resp.SearchConsolePageResp;
import com.gengzp.common.model.permission.resp.SearchPermissionsResp;
import com.gengzp.common.utils.DistributedLockUtils;
import com.gengzp.common.utils.ThreadUtils;
import com.gengzp.permission.annotation.AuthIgnore;
import com.gengzp.permission.annotation.CheckPermission;
import com.gengzp.system.service.PermissionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jakarta.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @ClassName PermissionController
 * @Description 权限管理控制层
 * @Author gengzp
 * @Date 2025/9/15 15:42
 */
@RestController
@RequestMapping("/permission")
@Api(tags = "权限管理模块")
public class PermissionController {

    private static final Logger logger = LoggerFactory.getLogger(PermissionController.class);

    @Autowired
    private PermissionService permissionService;

    /**
     * 查询所有权限列表
     */
    @AuthIgnore
    @OperationLogIgnore
    @PostMapping("/list")
    @ApiOperation(value = "查询权限列表")
    public Result<SearchPermissionsResp> searchAllPermissions() {
        return Result.getSuccessResult(permissionService.searchAllPermissions());
    }

    /**
     * 查询所有控制台管理页面权限
     */
    @AuthIgnore
    @OperationLogIgnore
    @PostMapping("/console_page/list")
    @ApiOperation(value = "查询所有控制台管理页面权限")
    public Result<List<SearchConsolePageResp>> searchAllConsolePages() {
        return Result.getSuccessResult(permissionService.searchAllConsolePages());
    }

    /**
     * 刷新角色权限的缓存信息
     */
    @PostMapping("/refresh_role_permission_cache")
    @ApiOperation(value = "刷新角色权限的缓存信息")
    @CheckPermission(value = "permission:allocate")
    public Result<Void> refreshRoleCache() {
        String lockKey = "refresh_role_permission";
        // 先校验锁是否被占用, 若被占用则直接返回报错
        if (DistributedLockUtils.verifyDistributedLockIsExist(lockKey)) {
            return Result.getFailResult("角色权限缓存刷新中, 请勿重复操作");
        }

        // 在子线程中刷新缓存
        ThreadUtils.execute(() ->
                // 启用分布式锁
                DistributedLockUtils.doExecuteWithLock(() -> {
                    long startTime = System.currentTimeMillis();
                    logger.info("开始刷新角色权限缓存...");
                    permissionService.refreshRoleCache();
                    logger.info("角色权限缓存刷新完成, 耗时: {}ms", System.currentTimeMillis() - startTime);
                }, lockKey));
        return Result.getSuccessResult();
    }

    /**
     * 为角色分配权限, 该方法会覆盖角色现有的权限
     */
    @PostMapping("/allocate_role_permission")
    @ApiOperation(value = "为角色分配权限, 该方法会覆盖角色现有的权限")
    @CheckPermission(value = "permission:allocate")
    public Result<Void> allocatePermissions(@Valid @RequestBody AllocatePermissionReq req) {
        permissionService.allocatePermissions(req);
        return Result.getSuccessResult();
    }

    /**
     * 为角色分配页面权限, 该方法会覆盖角色现有的页面权限
     */
    @PostMapping("/allocate_role_page")
    @ApiOperation(value = "为角色分配页面权限, 该方法会覆盖角色现有的页面权限")
    @CheckPermission(value = "permission:allocate")
    public Result<Void> allocatePages(@Valid @RequestBody AllocatePageReq req) {
        permissionService.allocatePages(req);
        return Result.getSuccessResult();
    }

    /**
     * 为用户分配角色, 该方法会覆盖用户现有的角色
     */
    @PostMapping("/allocate_user_role")
    @ApiOperation(value = "为用户分配角色, 该方法会覆盖用户现有的角色")
    @CheckPermission(value = "permission:allocate")
    public Result<Void> allocateRoles(@Valid @RequestBody AllocateRoleReq req) {
        permissionService.allocateRoles(req);
        return Result.getSuccessResult();
    }

}
